﻿/* Copyright (c) 2010 EPiServer AB
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
 * documentation files (the "Software"), to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
 * to permit persons to whom the Software is furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
 * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using EPiServer.Core;
using EPiServer.Security;
using EPiServer.Web;
using EPiServer.XForms;
using EPiServer.XForms.WebControls;
using RenderType = EPiServer.XForms.WebControls.RenderType;

namespace EPiServer.Municipality.Templates.Units {
    public partial class Form : UserControlBase {
        /* *******************************************************************
        *  Properties 
        * *******************************************************************/
        #region private EPiServer.XForms.XForm CurrentForm
        /// <summary>
        /// Get/Sets the Form of the Form
        /// </summary>
        /// <value></value>
        private XForm CurrentForm { get; set; }
        #endregion
        #region protected string FormHeading
        /// <summary>
        /// Gets the FormHeading of the Form
        /// </summary>
        /// <value></value>
        protected string FormHeading {
            get {
                if (IsValue("FormHeading"))
                    return (string)CurrentPage["FormHeading"];
                return string.Empty;
            }
        }
        #endregion
        #region private bool IsEditor
        /// <summary>
        /// Gets the IsEditor of the Form
        /// </summary>
        /// <value></value>
        private bool IsEditor {
            get {
                return PrincipalInfo.HasEditAccess;
            }
        }
        #endregion
        #region private bool IsFormVisible
        /// <summary>
        /// Gets the IsFormVisible of the Form
        /// </summary>
        /// <value></value>
        private bool IsFormVisible {
            get {
                if (IsValue("FormStartDate") && ((DateTime)CurrentPage["FormStartDate"]) > DateTime.Now)
                    return false;
                if (IsValue("FormStopDate") && ((DateTime)CurrentPage["FormStopDate"]) < DateTime.Now)
                    return false;
                return true;
            }
        }
        #endregion
        /* *******************************************************************
        *  Methods 
        * *******************************************************************/
        #region override protected void OnInit(EventArgs e)
        override protected void OnInit(EventArgs e) {
            InitializeComponent();
            base.OnInit(e);
        }
        #endregion
        #region private void InitializeComponent()
        private void InitializeComponent() {
            Init += Page_Init;
            Load += Page_Load;
            ExportToXMLButton.Click += ExportToXmlButtonClick;
            ExportToExcelButton.Click += ExportToExcelButtonClick;
        }
        #endregion
        #region private void RedirectAfterSubmit()
        /// <summary>
        /// 
        /// </summary>
        private void RedirectAfterSubmit() {
            if (FormControl.FormDefinition.IsSent) {
                PageReference pageReference = PermanentLinkUtility.FindPageReference(FormControl.FormDefinition.PageGuidAfterPost);
                if (PageReference.IsNullOrEmpty(pageReference)) {
                    return;
                }
                PageData pd = GetPage(pageReference);
                Page.Response.Redirect(pd.LinkURL);
            }
        }
        #endregion
        #region private void SetupForm()
        /// <summary>
        /// 
        /// </summary>
        private void SetupForm() {
            CurrentForm = XForm.CreateInstance(new Guid((String)CurrentPage["MainForm"]));
            CurrentForm.PageGuid = CurrentPage.PageGuid;
            if (Page.User.Identity.IsAuthenticated)
                CurrentForm.PostingUser = HttpContext.Current.User.Identity.Name;

            Statistics.PageGuid = CurrentForm.PageGuid;
            Statistics.PropertyName = "MainForm";
        }
        #endregion
        /* *******************************************************************
        *  Event methods 
        * *******************************************************************/
        #region private void Page_Init(object sender, EventArgs e)
        /// <summary>
        /// This method is called when the Page's Init event has been fired.
        /// </summary>
        /// <param name="sender">The <see cref="object"/> that fired the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> of the event.</param>
        private void Page_Init(object sender, EventArgs e) {
            if (CurrentPage.Property["MainForm"].IsNull) {
                Visible = false;
                return;
            }
            SetupForm();

            FormControl.FormDefinition = CurrentForm;
            FormValidationSummary.ValidationGroup = FormControl.ValidationGroup;
            FormControl.BeforeLoadingForm += FormControl_BeforeLoadingForm;
            FormControl.AfterSubmitPostedData += FormControl_AfterSubmitPostedData;
            FormControl.ControlsCreated += FormControl_ControlsCreated;
            FormControl.BeforeReadingPostedData += FormControl_CheckErrors;

        }
        #endregion
        #region private void Page_Load(object sender, EventArgs e)
        /// <summary>
        /// This method is called when the Page's Load event has been fired.
        /// </summary>
        /// <param name="sender">The <see cref="object"/> that fired the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> of the event.</param>
        private void Page_Load(object sender, EventArgs e) {
            if (IsEditor) {
                InternalInformationPlaceHolder.Visible = true;
                HitsCount.Text = String.Format(Translate("/municipality/units/form/numofposts"), Statistics.Posts.Rows.Count);
                ExportToXMLButton.Text = Translate("/municipality/units/form/exporttoxmlbutton");
                ExportToExcelButton.Text = Translate("/municipality/units/form/exporttoexcelbutton");
            }
            if (!IsFormVisible) {
                FormPlaceHolder.Visible = false;
            }
            if (!IsFormVisible && IsValue("FormExpiredMessage")) {
                FormExpiredPlaceHolder.Visible = true;
            }
        }
        #endregion
        #region private void FormControl_BeforeLoadingForm(object sender, LoadFormEventArgs e)
        /// <summary>
        /// This method is called when the FormControl's BeforeLoadingForm event has been fired.
        /// </summary>
        /// <param name="sender">The <see cref="object"/> that fired the event.</param>
        /// <param name="e">The <see cref="LoadFormEventArgs"/> of the event.</param>
        private static void FormControl_BeforeLoadingForm(object sender, LoadFormEventArgs e) {
            if (e.EditMode)
                return;

            var content = e.FormDefinition;
            const string regexMatchStringTables = "<table[^>]*?>([^<]*)?(<tbody>)?(.*?)(</tbody>)?([^<]*)?</table>";
            const string matchEvaluatorTables = "$3";
            content = Regex.Replace(content,
                                    regexMatchStringTables,
                                    matchEvaluatorTables,
                                    RegexOptions.Singleline
                                    | RegexOptions.IgnoreCase);


            const string regexMatchStringRows = "<tr[^>]*?>(.*?)</tr>";
            const string matchEvaluatorRows = "$1";
            content = Regex.Replace(content,
                                    regexMatchStringRows,
                                    matchEvaluatorRows,
                                    RegexOptions.Singleline
                                    | RegexOptions.IgnoreCase);


            const string regexMatchStringEmptyCells = "<td[^>]*?>(\\s*)</td>";
            const string matchEvaluatorEmptyCells = "$1";
            content = Regex.Replace(content,
                                    regexMatchStringEmptyCells,
                                    matchEvaluatorEmptyCells,
                                    RegexOptions.Singleline
                                    | RegexOptions.IgnoreCase);


            const string regexMatchStringCells = "<td[^>]*?>(.*?)</td>";
            const string matchEvaluatorCells = "$1";
            content = Regex.Replace(content,
                                    regexMatchStringCells,
                                    matchEvaluatorCells,
                                    RegexOptions.Singleline
                                    | RegexOptions.IgnoreCase);


            e.FormDefinition = content;

        }
        #endregion
        #region public void FormControl_AfterSubmitPostedData(object sender, SaveFormDataEventArgs e)
        /// <summary>
        /// This method is called when the FormControl's AfterSubmitPostedData event has been fired.
        /// </summary>
        /// <param name="sender">The <see cref="object"/> that fired the event.</param>
        /// <param name="e">The <see cref="SaveFormDataEventArgs"/> of the event.</param>
        public void FormControl_AfterSubmitPostedData(object sender, SaveFormDataEventArgs e) {
            RedirectAfterSubmit();
            FormPlaceHolder.Visible = false;
            FormMessage.Visible = true;
            FormMessage.Text = "<div class=\"systeminfo\"><div><strong>" + Translate("/municipality/units/form/sentmessage") + "</strong></div></div>";
        }
        #endregion
        #region public void FormControl_ControlsCreated(object sender, EventArgs e)
        /// <summary>
        /// This method is called when the FormControl's ControlsCreated event has been fired.
        /// </summary>
        /// <param name="sender">The <see cref="object"/> that fired the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> of the event.</param>
        public void FormControl_ControlsCreated(object sender, EventArgs e) {
            foreach (Control control in FormControl.Controls) {
                if (control is RequiredFieldValidator) {
                    ((RequiredFieldValidator)control).Display = ValidatorDisplay.None;
                    var xFormControl = (XFormControlBase)FormControl.FindControl(((RequiredFieldValidator)control).ControlToValidate);
                    ((RequiredFieldValidator)control).ErrorMessage = string.Format(Translate("/municipality/units/form/mandatorymessage"), xFormControl.Label);
                } else if (control is RegularExpressionValidator) {
                    ((RegularExpressionValidator)control).Display = ValidatorDisplay.None;
                    var xFormControl = (XFormControlBase)FormControl.FindControl(((RegularExpressionValidator)control).ControlToValidate);
                    ((RegularExpressionValidator)control).ErrorMessage = ((RegularExpressionValidator)control).ErrorMessage.Replace("*", xFormControl.Label);
                }
            }

            List<XFormControlBase> formcontrols = FormControl.ExtractXFormControls();
            foreach (XFormControlBase inputControl in formcontrols) {
                if (inputControl.Required) {
                    inputControl.Label += " <em>" + Translate("/municipality/units/form/mandatory") + "</em>";
                }
                if (inputControl is Input) {
                    inputControl.Attributes.Add("class", "text");
                }
                if (inputControl is TextArea) {
                    inputControl.Attributes.Add("class", "textarea");
                    inputControl.Attributes.Add("rows", "5");
                }
                if (inputControl is Submit)
                    inputControl.Attributes.Add("class", "button");
                //Select or radio buttons
                if (inputControl is Select1) {
                    var sel = inputControl as Select1;
                    if (sel.Appearence == RenderType.Minimal)
                        inputControl.Attributes.Add("class", "select");
                }
            }
        }
        #endregion
        #region public void FormControl_CheckErrors(object sender, SaveFormDataEventArgs e)
        /// <summary>
        /// This method is called when the FormControl's BeforeSubmitPostedData event has been fired.
        /// </summary>
        /// <param name="sender">The <see cref="object"/> that fired the event.</param>
        /// <param name="e">The <see cref="SaveFormDataEventArgs"/> of the event.</param>
        public void FormControl_CheckErrors(object sender, SaveFormDataEventArgs e) {
            Page.Validate(FormControl.ValidationGroup);
            if (!Page.IsValid) {
                List<XFormControlBase> formcontrols = FormControl.ExtractXFormControls();
                foreach (XFormControlBase inputControl in formcontrols) {
                    if (inputControl.Required && inputControl.Value == string.Empty || !inputControl.IsValidInput()) {
                        if (inputControl is Input || inputControl is TextArea || inputControl is SelectControl)
                            inputControl.Attributes["class"] += " error";
                    }
                }
            }
        }
        #endregion
        /* *******************************************************************
        *  Form data export methods 
        * *******************************************************************/
        #region protected void ExportToXmlButtonClick(object sender, EventArgs e)
        /// <summary>
        /// This method is called when the ExportToXMLButton's Click event has been fired.
        /// </summary>
        /// <param name="sender">The <see cref="object"/> that fired the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> of the event.</param>
        protected void ExportToXmlButtonClick(object sender, EventArgs e) {
            string s = GetFormatedPostedDataSet().GetXml().Replace("NewDataSet", "FormPostings");
            Response.Clear();
            Response.AddHeader("content-disposition", "fileattachment;filename=xFormData.xml");
            Response.ContentType = "text/xml";
            Response.Write(s);
            Response.End();
        }
        #endregion
        #region protected void ExportToExcelButtonClick(object sender, EventArgs e)
        /// <summary>
        /// This method is called when the ExportToExcelButton's Click event has been fired.
        /// </summary>
        /// <param name="sender">The <see cref="object"/> that fired the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> of the event.</param>
        protected void ExportToExcelButtonClick(object sender, EventArgs e) {
            DataSet formatedPostedDataSet = GetFormatedPostedDataSet();
            Response.Clear();
            Response.ContentType = "application/vnd.ms-excel";
            Response.ContentEncoding = Encoding.Unicode;
            Response.AddHeader("content-disposition", "fileattachment;filename=xFormData.xls");
            Response.BinaryWrite(new byte[] { 0xff, 0xfe });
            using (var writer = new StringWriter()) {
                using (var writer2 = new HtmlTextWriter(writer)) {
                    var grid = new DataGrid();
                    grid.DataSource = formatedPostedDataSet.Tables[0];
                    grid.GridLines = GridLines.Both;
                    grid.HeaderStyle.Font.Bold = true;
                    grid.AllowPaging = false;
                    grid.DataBind();
                    grid.RenderControl(writer2);
                    Response.Write(writer.ToString());
                    Response.End();
                }
            }
        }
        #endregion
        #region protected DataSet GetFormatedPostedDataSet()
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        protected DataSet GetFormatedPostedDataSet() {
            DataSet set = DataforExport();
            var table = new DataTable("record");
            foreach (DataColumn column in set.Tables[0].Columns) {
                var column2 = new DataColumn();
                if (string.Compare(column.ColumnName, "DATEPOSTED", StringComparison.OrdinalIgnoreCase) == 0) {
                    column2.DataType = Type.GetType("System.String");
                    column2.ColumnName = column.ColumnName;
                } else {
                    column2.ColumnName = column.ColumnName;
                }
                table.Columns.Add(column2);
            }
            DataTable table2 = set.Tables[0];
            foreach (DataRow row in table2.Rows) {
                table.ImportRow(row);
            }
            var set2 = new DataSet();
            set2.Tables.Add(table);
            return set2;
        }
        #endregion
        #region private DataSet DataforExport()
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        private DataSet DataforExport() {
            DataView defaultView = Statistics.Posts.DefaultView;
            var set = new DataSet();
            var set2 = new DataSet();
            set.Tables.Add(defaultView.Table);
            DataTable table = set.Tables[0].DefaultView.Table.Clone();
            foreach (DataRowView view2 in set.Tables[0].DefaultView) {
                table.ImportRow(view2.Row);
            }
            table.Columns.Remove("ID");
            table.Columns.Remove("PostingID");
            table.AcceptChanges();
            set2.Tables.Add(table);
            set2.Tables[0].TableName = "Record";
            table.Dispose();
            set.Dispose();
            defaultView.Dispose();
            return set2;
        }
        #endregion
    }
}